﻿//using DotNetCommon.Data;
//using DotNetCommon.Extensions;
//using DotNetCommon.Logger;
//using System;
//using System.Collections.Concurrent;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using System.Reflection.Emit;
//using System.Text;
//using System.Threading;
//using System.Threading.Tasks;

//namespace DotNetCommon;

///// <summary>
///// 基于Roslyn的Mapper
///// </summary>
//public class RoslynMapper
//{
//    private static readonly ILogger<RoslynMapper> logger = LoggerFactory.CreateLogger<RoslynMapper>();
//    /// <summary>
//    /// 当RoslynMapper触发时产生事件
//    /// </summary>
//    public static event Action<Context, Result<Assembly>> EventRoslynMapperTriggered;
//    #region 代码生成
//    #region 模型
//    /// <summary>
//    /// 生成代码上下文
//    /// </summary>
//    public class Context
//    {
//        /// <summary>
//        /// 命名空间
//        /// </summary>
//        public List<string> NameSpaces { get; set; }
//        /// <summary>
//        /// 转换方法
//        /// </summary>
//        public List<MapContext> Methods { get; set; }

//        /// <summary>
//        /// 生成的code
//        /// </summary>
//        public string Code { get; set; }
//        /// <summary>
//        /// 类名称
//        /// </summary>
//        public string ClassName { get; set; }
//    }

//    /// <summary>
//    /// 实体映射(表示一个转换方法)
//    /// </summary>
//    public class MapContext
//    {
//        /// <summary>
//        /// 源type名称(内部类包含外层名称)
//        /// </summary>
//        public string SrcTypeName { get; set; }
//        /// <summary>
//        /// 源type
//        /// </summary>
//        public Type SrcType { get; set; }
//        /// <summary>
//        /// 目标type名称(内部类包含外层名称)
//        /// </summary>
//        public string DestTypeName { get; set; }
//        /// <summary>
//        /// 目标type
//        /// </summary>
//        public Type DestType { get; set; }

//        /// <summary>
//        /// 属性映射
//        /// </summary>
//        public List<PropContext> Props { get; set; }

//        /// <summary>
//        /// 转换方法名字
//        /// </summary>
//        public string MethodName { get; set; }

//        /// <summary>
//        /// 目标类型名称
//        /// </summary>
//        public string SrcTypeVarName { get; set; }

//        /// <summary>
//        /// 目标类型名称
//        /// </summary>
//        public string DestTypeVarName { get; set; }

//        /// <summary>
//        /// 是否目标是数组
//        /// </summary>
//        public bool IsToArray { get; set; }

//        /// <summary>
//        /// 是否目标是List
//        /// </summary>
//        public bool IsToList { get; set; }

//        /// <summary>
//        /// 当这个转换是针对集合时引用的其他转换方法
//        /// </summary>
//        public MapContext InnerMap { get; set; }

//        /// <summary>
//        /// 包含的转换
//        /// </summary>
//        public List<(Type fromType, Type destType)> ConvertTypes { get; set; }

//        /// <summary>
//        /// 是否需要容器缓存,只有当模型本身可能存在循环引用的时候才使用缓存
//        /// </summary>
//        public bool NeedContainer { get; set; }

//        /// <summary>
//        /// 是否暴露出去(当子级因为父级而要防循环,但本身并不需要防循环时 为 false)
//        /// </summary>
//        public bool IsExpose { get; set; } = true;

//        /// <summary>
//        /// 是否是分裂生成的方法
//        /// </summary>
//        public bool IsSplit { get; set; } = false;
//    }

//    /// <summary>
//    /// 属性映射(表示实体的一个属性转换)
//    /// </summary>
//    public class PropContext : MapContext
//    {
//        /// <summary>
//        /// 是否是序列
//        /// </summary>
//        public bool IsSequence { get; set; }
//        /// <summary>
//        /// 是否终止遍历
//        /// </summary>
//        public bool IsEnd { get; set; }

//        /// <summary>
//        /// 该属性需要的其他转换方法
//        /// </summary>
//        public MapContext Map { get; set; }

//        /// <summary>
//        /// 目标属性
//        /// </summary>
//        public PropertyInfo DestPropInfo { get; set; }
//        /// <summary>
//        /// 源属性
//        /// </summary>
//        public PropertyInfo SrcPropInfo { get; set; }
//    }
//    #endregion
//    private Context ctx = new Context();
//    private static int Counter = 0;
//    /// <summary>
//    /// 生成不同类型映射代码
//    /// </summary>
//    /// <param name="src">源类型</param>
//    /// <param name="dest">目标类型</param>
//    /// <returns></returns>
//    public Context GenerateMapCode(Type src, Type dest)
//    {
//        if (src == typeof(string) || dest == typeof(string)) throw new ArgumentException($"{nameof(dest)}和{nameof(src)} 都不要使用String!");
//        if (src.IsValueType || dest.IsValueType) throw new ArgumentException($"{nameof(dest)}和{nameof(src)} 都不要使用值类型!");
//        var b1 = src.IsConvertCollectionsOrArrary();
//        var b2 = dest.IsConvertCollectionsOrArrary();
//        if (b1 != b2) throw new ArgumentException("转换的源类型和目标类型不能一方为集合,而另一方不是!");

//        ctx.NameSpaces = new List<string>()
//        {
//            "DotNetCommon.Extensions",
//            "System.Linq",
//            "System",
//            "System.IO",
//            "System.Collections",
//            "System.Collections.Generic",
//            "DotNetCommon.Serialize"
//        };

//        if (src.IsConvertCollectionsOrArrary() && dest.IsConvertCollectionsOrArrary())
//        {
//            Type srcFType = src.IsArray ? src.GetElementType() : src.GenericTypeArguments[0];
//            Type destFType = dest.IsArray ? dest.GetElementType() : dest.GenericTypeArguments[0];
//            return GenerateMapCode(srcFType, destFType);
//        }

//        ctx.Methods = new List<MapContext>();
//        //遍历结构
//        Visit(src, dest);
//        //处理NeedContainer
//        DealNeedCache();

//        //生成代码
//        var sb = new StringBuilder();
//        var builder = new CodeStringBuilder(sb);
//        builder.AppendLine("namespace DotNetCommon.MapperGenerator");
//        builder.AppendLine("{");
//        builder.SetIdent(1);
//        ctx.NameSpaces.ForEach(s => builder.AppendLine($"using {s};"));
//        var clsName = $"MapperClass{Counter}";
//        var clsFullName = $"DotNetCommon.MapperGenerator.{clsName}";
//        ctx.ClassName = clsFullName;
//        builder.AppendLine($"public static class {clsName}");
//        builder.AppendLine($"{{");
//        builder.SetIdent(2);
//        //生成变量
//        var listTypeNames = new List<string>();
//        for (int i = 0; i < ctx.Methods.Count; i++)
//        {
//            var method = ctx.Methods[i];
//            if (method.IsToArray || method.IsToList) continue;
//            //分裂出来的不需要
//            if (method.DestTypeVarName.StartsWith("typesplit")) continue;
//            if (!listTypeNames.Contains(method.SrcTypeVarName))
//            {
//                builder.AppendLine($"private static Type {method.SrcTypeVarName} = typeof({method.SrcTypeName});");
//                listTypeNames.Add(method.SrcTypeVarName);
//            }
//            if (!listTypeNames.Contains(method.DestTypeVarName))
//            {
//                builder.AppendLine($"private static Type {method.DestTypeVarName} = typeof({method.DestTypeName});");
//                listTypeNames.Add(method.DestTypeName);
//            }
//        }
//        builder.AppendLine("");

//        for (int i = 0; i < ctx.Methods.Count; i++)
//        {
//            var method = ctx.Methods[i];
//            #region 添加描述,便于调试
//            var desc = $"//{method.SrcTypeName} => {method.DestTypeName}";
//            builder.AppendLine(desc);
//            var srcShort = method.SrcTypeName;
//            var destShort = method.DestTypeName;
//            if (method.IsToArray || method.IsToList)
//            {
//                var tmp = method.SrcTypeName.SplitAndTrimTo<string>(".").LastOrDefault();
//                var tmp2 = method.DestTypeName.SplitAndTrimTo<string>(".").LastOrDefault();
//                if (tmp.Contains("<"))
//                {
//                    srcShort = "IEnumerable<" + tmp + ">";
//                }
//                else
//                {
//                    srcShort = "IEnumerable<" + tmp.Replace(">", "") + ">";
//                }
//                if (method.IsToList)
//                {
//                    if (tmp2.Contains("<"))
//                    {
//                        destShort = "List<" + tmp2 + ">";
//                    }
//                    else
//                    {
//                        destShort = "List<" + tmp2.Replace(">", "") + ">";
//                    }
//                }
//                else
//                {
//                    destShort = tmp2;
//                }
//            }
//            else
//            {
//                srcShort = method.SrcTypeName.SplitAndTrimTo<string>(".").LastOrDefault();
//                destShort = method.DestTypeName.SplitAndTrimTo<string>(".").LastOrDefault();
//            }
//            desc = $"//{srcShort} => {destShort} {(method.NeedContainer ? "防循环引用" : "不用防")}";
//            builder.AppendLine(desc);
//            #endregion
//            builder.AppendLine($"{(method.IsExpose ? "public" : "private")} static object {method.MethodName}(object srcObj, Dictionary<(object src, Type srcType, Type destType), object> container = null)");
//            builder.AppendLine($"{{");
//            builder.SetIdent(3);
//            builder.AppendLine("if (srcObj == null) return null;");
//            builder.AppendLine($"var src = srcObj as {method.SrcTypeName};");
//            if (method.NeedContainer)
//            {
//                //大部分情况下不需要缓存容器,提升性能
//                builder.AppendLine("if (container == null) container = new Dictionary<(object src, Type srcType, Type destType), object>();");
//                builder.AppendLine($"var key = (src,{method.SrcTypeVarName},{method.DestTypeVarName});");
//                builder.AppendLine($"if(container.ContainsKey(key)) return ({method.DestTypeName})container[key];");
//            }
//            if (method.IsToArray)
//            {
//                builder.AppendLine($"var res = src.Select(i => ({method.InnerMap.DestTypeName}){method.InnerMap.MethodName}(i,container)).ToArray();");
//            }
//            else if (method.IsToList)
//            {
//                builder.AppendLine($"var res = src.Select(i => ({method.InnerMap.DestTypeName}){method.InnerMap.MethodName}(i,container)).ToList();");
//            }
//            else
//            {
//                builder.AppendLine($"var res = new {method.DestTypeName}();");
//                if (method.NeedContainer)
//                {
//                    //大部分情况下不需要缓存容器,提升性能
//                    builder.AppendLine($"container.Add(key,res);");
//                }
//                for (var j = 0; j < method.Props.Count; j++)
//                {
//                    var prop = method.Props[j];
//                    if (prop.IsEnd)
//                    {
//                        #region 直接转换
//                        if (prop.IsSequence)
//                        {
//                            #region 集合
//                            builder.AppendLine($"if(src.{prop.DestPropInfo.Name} == null)");
//                            builder.AppendLine($"{{");
//                            builder.SetIdent(4);
//                            builder.AppendLine($"res.{prop.DestPropInfo.Name}=null;");
//                            builder.SetIdent(3);
//                            builder.AppendLine($"}}");
//                            builder.AppendLine($"else");
//                            builder.AppendLine($"{{");
//                            builder.SetIdent(4);
//                            var srcFType = prop.SrcType.IsArray ? prop.SrcType.GetElementType() : prop.SrcType.GenericTypeArguments[0];
//                            var destFType = prop.DestType.IsArray ? prop.DestType.GetElementType() : prop.DestType.GenericTypeArguments[0];
//                            //处理内部不一致
//                            var select = "";
//                            if (destFType != srcFType)
//                            {
//                                if (destFType.IsAssignableFrom(srcFType))
//                                {
//                                    select = $".Select(i => ({destFType.GetClassFullName()})i)";
//                                }
//                                else
//                                {
//                                    if (!destFType.IsNullable() && srcFType.IsNullable())
//                                    {
//                                        // int? -> int
//                                        var srcType2 = srcFType.GenericTypeArguments[0];
//                                        if (srcType2 == destFType)
//                                        {
//                                            select = $".Select(i => i?? default({destFType.GetClassFullName()}))";
//                                        }
//                                        else
//                                        {
//                                            select = $".Select(i => i == null ? default({destFType.GetClassFullName()}) : ({destFType.GetClassFullName()})i.To(typeof({destFType.GetClassFullName()})))";
//                                        }
//                                    }
//                                    else if (!destFType.IsNullable() && !srcFType.IsValueType)
//                                    {
//                                        select = $".Select(i => i == null ? default({destFType.GetClassFullName()}) : ({destFType.GetClassFullName()})i.To(typeof({destFType.GetClassFullName()})))";
//                                    }
//                                    else if (destFType == typeof(string))
//                                    {
//                                        if (!srcFType.IsNullable() && srcFType.IsValueType) select = $".Select(i => i.ToString())";
//                                        else select = $".Select(i => i?.ToString())";
//                                    }
//                                    else
//                                    {
//                                        select = $".Select(i => ({destFType.GetClassFullName()})i.To(typeof({destFType.GetClassFullName()})))";
//                                    }
//                                }
//                            }

//                            if (prop.DestType.IsArray)
//                            {
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}{select}.ToArray();");
//                            }
//                            else
//                            {
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}{select}.ToList();");
//                            }
//                            builder.SetIdent(3);
//                            builder.AppendLine($"}}");
//                            #endregion
//                        }
//                        else
//                        {
//                            #region 非集合
//                            if (prop.DestType.IsAssignableFrom(prop.SrcType))
//                            {
//                                //可以直接转
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name};");
//                                continue;
//                            }

//                            if (!prop.DestType.IsNullable() && prop.SrcType.IsNullable())
//                            {
//                                // int? -> int
//                                var srcType = prop.SrcType.GenericTypeArguments[0];
//                                if (srcType == prop.DestType)
//                                {
//                                    builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name} ?? default({prop.DestTypeName});");
//                                    continue;
//                                }
//                                else
//                                {
//                                    builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name} == null ? default({prop.DestTypeName}) :  ({prop.DestTypeName})src.{prop.SrcPropInfo.Name}.To(typeof({prop.DestTypeName}));");
//                                    continue;
//                                }
//                            }
//                            else if (!prop.DestType.IsNullable() && !prop.SrcType.IsValueType)
//                            {
//                                // string => int
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name} == null ? default({prop.DestTypeName}) :  ({prop.DestTypeName})src.{prop.SrcPropInfo.Name}.To(typeof({prop.DestTypeName}));");
//                                continue;
//                            }
//                            else if (prop.DestType == typeof(string))
//                            {
//                                #region 其他类型转string
//                                // other => string
//                                if (prop.SrcType == typeof(DateTime) || prop.SrcType == typeof(DateTime?)
//                                    || prop.SrcType == typeof(DateTimeOffset) || prop.SrcType == typeof(DateTimeOffset?)
//                                    || prop.SrcType == typeof(Guid) || prop.SrcType == typeof(Guid?))
//                                {
//                                    //日期或guid转字符串
//                                    var converter = prop.SrcPropInfo
//                                        .GetCustomAttributes()
//                                        .FirstOrDefault(i => i.GetType() == typeof(MapperArgumentsAttribute)) as MapperArgumentsAttribute;
//                                    if (converter == null)
//                                    {
//                                        converter = prop.DestPropInfo
//                                        .GetCustomAttributes()
//                                        .FirstOrDefault(i => i.GetType() == typeof(MapperArgumentsAttribute)) as MapperArgumentsAttribute;
//                                    }
//                                    if (converter != null && converter.Args?.Length > 0)
//                                    {
//                                        var formatter = converter.Args.FirstOrDefault().ToString();
//                                        if (formatter.IsNotNullOrWhiteSpace())
//                                        {
//                                            builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}{(prop.SrcType.IsNullable() ? "?" : "")}.ToString(\"{formatter}\");");
//                                            continue;
//                                        }
//                                    }
//                                }
//                                //其他类型 -> string
//                                if (!prop.SrcType.IsValueType || prop.SrcType.IsNullable())
//                                {
//                                    //Object -> string 或 int? -> string
//                                    builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}?.ToString();");
//                                }
//                                else
//                                {
//                                    //值类型且不可空
//                                    builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}.ToString();");
//                                }
//                                continue;
//                                #endregion
//                            }
//                            if (prop.DestType == typeof(DateTime) || prop.DestType == typeof(DateTime?)
//                                || prop.DestType == typeof(DateTimeOffset) || prop.DestType == typeof(DateTimeOffset?)
//                                || prop.DestType == typeof(Guid) || prop.DestType == typeof(Guid?))
//                            {
//                                if (prop.SrcType == typeof(string))
//                                {
//                                    #region 字符串转日期或guid
//                                    var typeName = prop.DestType.GetClassFullName();
//                                    var converter = prop.SrcPropInfo
//                                        .GetCustomAttributes()
//                                        .FirstOrDefault(i => i.GetType() == typeof(MapperArgumentsAttribute)) as MapperArgumentsAttribute;
//                                    if (converter == null)
//                                    {
//                                        converter = prop.DestPropInfo
//                                        .GetCustomAttributes()
//                                        .FirstOrDefault(i => i.GetType() == typeof(MapperArgumentsAttribute)) as MapperArgumentsAttribute;
//                                    }
//                                    var type = "";
//                                    if (prop.DestType == typeof(Guid) || prop.DestType == typeof(Guid?)) type = "Guid";
//                                    else if (prop.DestType == typeof(DateTime) || prop.DestType == typeof(DateTime?)) type = "DateTime";
//                                    else type = "DateTimeOffSet";
//                                    if (converter != null && converter.Args?.Length > 0)
//                                    {
//                                        var formatter = converter.Args.FirstOrDefault().ToString();
//                                        if (formatter.IsNotNullOrWhiteSpace())
//                                        {
//                                            if (prop.DestType.IsNullable())
//                                            {
//                                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name} == null?null:({typeName})src.{prop.SrcPropInfo.Name}.To(typeof({typeName}), \"{formatter}\");");
//                                            }
//                                            else
//                                            {
//                                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}.IsNullOrWhiteSpace()?default({type}):({typeName})src.{prop.SrcPropInfo.Name}.To(typeof({typeName}), \"{formatter}\");");
//                                            }
//                                            continue;
//                                        }
//                                    }
//                                    var nulldefault = "null";
//                                    if (!prop.DestType.IsNullable()) nulldefault = $"default({type})";
//                                    builder.AppendLine($"res.{prop.DestPropInfo.Name} =  src.{prop.SrcPropInfo.Name}.IsNullOrWhiteSpace()?{nulldefault}:({typeName})src.{prop.SrcPropInfo.Name}.Parse(src.{prop.DestPropInfo.Name});");
//                                    continue;
//                                    #endregion
//                                }
//                            }
//                            //其他类型 -> 其他类型
//                            builder.AppendLine($"res.{prop.DestPropInfo.Name} = ({prop.DestTypeName})src.{prop.SrcPropInfo.Name}.To(typeof({prop.DestTypeName}));");
//                            #endregion
//                        }
//                        #endregion
//                    }
//                    else
//                    {
//                        #region 调用其他转换
//                        if (prop.IsSequence)
//                        {
//                            //集合
//                            builder.AppendLine($"if(src.{prop.DestPropInfo.Name} == null)");
//                            builder.AppendLine($"{{");
//                            builder.SetIdent(4);
//                            builder.AppendLine($"res.{prop.DestPropInfo.Name}=null;");
//                            builder.SetIdent(3);
//                            builder.AppendLine($"}}");
//                            builder.AppendLine($"else");
//                            builder.AppendLine($"{{");
//                            builder.SetIdent(4);
//                            if (prop.DestType.IsArray)
//                            {
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}.Select(i=>{prop.Map.MethodName}(i, container) as {prop.Map.DestTypeName}).ToArray();");
//                            }
//                            else
//                            {
//                                builder.AppendLine($"res.{prop.DestPropInfo.Name} = src.{prop.SrcPropInfo.Name}.Select(i=>{prop.Map.MethodName}(i, container) as {prop.Map.DestTypeName}).ToList();");
//                            }
//                            builder.SetIdent(3);
//                            builder.AppendLine($"}}");
//                        }
//                        else
//                        {
//                            builder.AppendLine($"res.{prop.DestPropInfo.Name} = ({prop.Map.DestTypeName}){prop.Map.MethodName}(src.{prop.SrcPropInfo.Name}, container);");
//                        }
//                        #endregion
//                    }
//                }
//            }
//            builder.AppendLine("return res;");
//            builder.SetIdent(2);
//            builder.AppendLine("}");
//            builder.AppendLine("");
//        }
//        builder.SetIdent(1);
//        builder.AppendLine("}");
//        builder.SetIdent(0);
//        builder.AppendLine("}");
//        ctx.Code = builder.ToString();
//        return ctx;
//    }

//    private void DealNeedCache()
//    {
//        var methods = ctx.Methods.Where(i => i.IsToArray == false && i.IsToList == false).ToList();
//        //先判断哪些需要防循环,哪些不需要

//        var cacheTypes = new Dictionary<MapContext, List<(Type fromType, Type destType)>>();
//        foreach (var method in methods)
//        {
//            var types = new List<(Type fromType, Type destType)>() { (method.SrcType, method.DestType) };
//            recursion0(method, new List<MapContext>(), types);
//            cacheTypes.Add(method, types);
//        }
//        foreach (var method in methods)
//        {
//            method.ConvertTypes = cacheTypes[method];
//        }
//        void recursion0(MapContext mapContext, List<MapContext> container, List<(Type fromType, Type destType)> convertTypes)
//        {
//            if (container.Contains(mapContext)) return;
//            container.Add(mapContext);
//            convertTypes.AddRange(mapContext.ConvertTypes ?? new List<(Type fromType, Type destType)>());
//            var props = mapContext.Props.Where(i => !i.IsEnd).ToList();
//            foreach (var prop in props)
//            {
//                recursion0(prop.Map, container, convertTypes);
//            }
//        }
//        //当出现重复的时候设置NeedContainer=true
//        methods.ForEach(m => m.NeedContainer = m.ConvertTypes.GroupBy(i => i).Any(i => i.Count() > 1));

//        //因为子级要防循环引用,所以父级肯定也要防
//        //第一次遍历,找出因为子级需要容器,牵连父级也必须要容器
//        var needs = methods.Where(i => i.NeedContainer).ToList();
//        var noNeeds = methods.Where(i => i.NeedContainer == false).ToList();
//        List<MapContext> newNeeds = null;
//        do
//        {
//            List<MapContext> tmp = null;
//            if (newNeeds == null)
//            {
//                //第一次
//                tmp = needs;
//            }
//            else
//            {
//                tmp = newNeeds;
//            }
//            recursion(tmp);
//        } while (noNeeds.Count > 0 && newNeeds.Count > 0);


//        //已知needs是需要容器的, 从noNeeds查找出来引用了它们的,那么查找出来的肯定也需要容器
//        void recursion(List<MapContext> mapContext)
//        {
//            var refs = noNeeds.Where(i => i.Props.Any(p => mapContext.Contains(p.Map))).ToList();
//            refs.ForEach(i => i.NeedContainer = true);
//            newNeeds = new List<MapContext>();
//            newNeeds.AddRange(refs);
//            refs.ForEach(i => noNeeds.Remove(i));
//        }

//        //第二次遍历,找出父级需要容器,但自身不需要容器的
//        methods = ctx.Methods.Where(i => i.IsToArray == false && i.IsToList == false).ToList();
//        needs = methods.Where(i => i.NeedContainer).ToList();

//        //需要分裂的(只包含顶级)
//        var alreadyVisit = new List<MapContext>();
//        noNeeds = new List<MapContext>();
//        needs.ForEach(i => recursion2(i));

//        //第三次, 进行分裂处理
//        noNeeds.ForEach(i =>
//        {
//            var map = recursion3(i);
//            ctx.Methods.Add(map);
//        });

//        void recursion2(MapContext mapContext)
//        {
//            if (alreadyVisit.Contains(mapContext)) return;
//            alreadyVisit.Add(mapContext);
//            var props = mapContext.Props.Where(i => !i.IsEnd);
//            foreach (var prop in props)
//            {
//                if (prop.Map.NeedContainer)
//                {
//                    recursion2(prop.Map);
//                    continue;
//                }
//                recursion22(prop.Map);
//            };
//        }
//        void recursion22(MapContext mapContext)
//        {
//            if (!noNeeds.Contains(mapContext))
//            {
//                noNeeds.Add(mapContext);
//                mapContext.Props.Where(i => !i.IsEnd).ForEach(i => recursion22(i.Map));
//            }
//        }
//        MapContext recursion3(MapContext mapContext)
//        {
//            //将原来的改成需要容器且不暴露
//            mapContext.IsExpose = false;
//            mapContext.NeedContainer = true;
//            //分裂一个新的
//            var counter = Interlocked.Increment(ref Counter);
//            var methodName = $"Map{counter}";
//            var newMap = new MapContext
//            {
//                DestType = mapContext.DestType,
//                DestTypeName = mapContext.DestTypeName,
//                SrcTypeVarName = $"typesplit{counter}_0",
//                DestTypeVarName = $"typesplit{counter}_1",
//                InnerMap = mapContext.InnerMap,
//                IsExpose = true,
//                IsToArray = mapContext.IsToArray,
//                IsToList = mapContext.IsToList,
//                MethodName = methodName,
//                NeedContainer = false,
//                Props = new List<PropContext>(),//先置为空
//                SrcType = mapContext.SrcType,
//                SrcTypeName = mapContext.SrcTypeName,
//                IsSplit = true
//            };
//            mapContext.Props.ForEach(p =>
//            {
//                if (p.IsEnd)
//                {
//                    newMap.Props.Add(p);
//                    return;
//                }
//                var prop = new PropContext
//                {
//                    DestPropInfo = p.DestPropInfo,
//                    IsToArray = p.IsToArray,
//                    Props = p.Props,
//                    DestType = p.DestType,
//                    DestTypeName = p.DestTypeName,
//                    DestTypeVarName = p.DestTypeName,
//                    InnerMap = p.InnerMap,
//                    IsEnd = p.IsEnd,
//                    IsExpose = p.IsExpose,
//                    IsSequence = p.IsSequence,
//                    IsToList = p.IsToList,
//                    Map = null,
//                    MethodName = p.MethodName,
//                    NeedContainer = p.NeedContainer,
//                    SrcPropInfo = p.SrcPropInfo,
//                    SrcType = p.SrcType,
//                    SrcTypeName = p.SrcTypeName
//                };
//                var map = ctx.Methods.FirstOrDefault(i => i.SrcType == p.Map.SrcType && i.DestType == p.Map.DestType && i.NeedContainer == false);
//                if (map != null)
//                {
//                    prop.Map = map;
//                }
//                else
//                {
//                    prop.Map = recursion3(p.Map);
//                }
//                newMap.Props.Add(prop);
//            });
//            return newMap;
//        }
//    }

//    private MapContext Visit(Type src, Type dest)
//    {
//        var srcNamespace = src.Namespace;
//        var destNamespace = dest.Namespace;
//        var counter = Interlocked.Increment(ref Counter);
//        var methodName = $"Map{counter}";
//        var mapCtx = new MapContext()
//        {
//            SrcType = src,
//            SrcTypeName = src.GetClassFullName(),
//            DestType = dest,
//            DestTypeName = dest.GetClassFullName(),
//            Props = new List<PropContext>(),
//            MethodName = methodName,
//            SrcTypeVarName = $"type{counter}_0",
//            DestTypeVarName = $"type{counter}_1",
//            IsToArray = false,
//            IsToList = false,
//            ConvertTypes = new List<(Type fromType, Type destType)>()
//        };
//        ctx.Methods.Add(mapCtx);
//        #region 增加集合转换支持
//        //增加集合转换支持
//        //ToArray
//        var tmpSrcType = typeof(IEnumerable<>).MakeGenericType(src);
//        var tmpDestType = dest.MakeArrayType();
//        var extMap = new MapContext()
//        {
//            SrcType = tmpSrcType,
//            SrcTypeName = tmpSrcType.GetClassFullName(),
//            DestType = tmpDestType,
//            DestTypeName = tmpDestType.GetClassFullName(),
//            Props = new List<PropContext>(),
//            MethodName = $"Map2Array{counter}",
//            SrcTypeVarName = $"typeArray{counter}_0",
//            DestTypeVarName = $"typeArray{counter}_1",
//            InnerMap = mapCtx,
//            IsToArray = true,
//            IsToList = false,
//        };
//        ctx.Methods.Add(extMap);
//        //ToList 
//        tmpDestType = typeof(List<>).MakeGenericType(src);
//        extMap = new MapContext()
//        {
//            SrcType = tmpSrcType,
//            SrcTypeName = tmpSrcType.GetClassFullName(),
//            DestType = tmpDestType,
//            DestTypeName = tmpDestType.GetClassFullName(),
//            Props = new List<PropContext>(),
//            MethodName = $"Map2List{counter}",
//            SrcTypeVarName = $"typeList{counter}_0",
//            DestTypeVarName = $"typeList{counter}_1",
//            InnerMap = mapCtx,
//            IsToArray = false,
//            IsToList = true,
//        };
//        ctx.Methods.Add(extMap);
//        #endregion
//        var srcProps = src.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
//        var destProps = dest.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(i => i.CanWrite).ToList();
//        for (var i = 0; i < destProps.Count; i++)
//        {
//            var destProp = destProps[i];
//            var srcProp = srcProps.FirstOrDefault(i => i.Name == destProp.Name);
//            if (srcProp == null) continue;
//            var srcType = srcProp.PropertyType;
//            var destType = destProp.PropertyType;
//            var propContxt = new PropContext
//            {
//                DestPropInfo = destProp,
//                SrcPropInfo = srcProp,
//                DestType = destProp.PropertyType,
//                SrcType = srcProp.PropertyType,
//                SrcTypeName = srcProp.PropertyType.GetClassFullName(),
//                DestTypeName = destProp.PropertyType.GetClassFullName()
//            };
//            mapCtx.Props.Add(propContxt);
//            //简单类型终止
//            if (srcType.IsSimpleType() || destType.IsSimpleType())
//            {
//                propContxt.IsEnd = true;
//                continue;
//            }
//            //可以兼容的终止
//            if (destType == srcType)
//            {
//                propContxt.IsEnd = true;
//                continue;
//            }

//            if (srcType.IsConvertCollectionsOrArrary() && destType.IsConvertCollectionsOrArrary())
//            {
//                //集合或数组 它们之间可以互转
//                propContxt.IsSequence = true;
//                Type srcFType = srcType.IsConvertCollections() ? srcType.GenericTypeArguments[0] : srcType.GetElementType();
//                Type destFType = destType.IsConvertCollections() ? destType.GenericTypeArguments[0] : destType.GetElementType();
//                if (destFType.IsSimpleType() || srcFType.IsSimpleType())
//                {
//                    propContxt.IsEnd = true;
//                }
//                else
//                {
//                    var tmp2 = ctx.Methods.Find(ctx => ctx.SrcType == srcFType && ctx.DestType == destFType);
//                    mapCtx.ConvertTypes.Add((srcFType, destFType));
//                    if (tmp2 != null)
//                    {
//                        //已经有转换方法了
//                        propContxt.Map = tmp2;
//                    }
//                    else
//                    {
//                        //新生成转换
//                        propContxt.Map = Visit(srcFType, destFType);
//                    }
//                }
//            }
//            else
//            {
//                //都不是集合或数组
//                var tmp = ctx.Methods.Find(ctx => ctx.SrcType == srcType && ctx.DestType == destType);
//                mapCtx.ConvertTypes.Add((srcType, destType));
//                if (tmp != null)
//                {
//                    //已经有转换方法了
//                    propContxt.Map = tmp;
//                }
//                else
//                {
//                    //新生成转换
//                    propContxt.Map = Visit(srcType, destType);
//                }
//            }
//        }
//        return mapCtx;
//    }

//    internal static List<string> CollectNames = new List<string>()
//    {
//        "System.Collections.Generic.List`1",
//        "System.Collections.Generic.IList`1",
//        "System.Collections.Generic.IEnumerable`1",
//        "System.Collections.Generic.ICollection`1"
//    };

//    private class CodeStringBuilder
//    {
//        private readonly StringBuilder sb;

//        public CodeStringBuilder(StringBuilder sb)
//        {
//            this.sb = sb;
//        }

//        private string indent = "";
//        public void SetIdent(int indent = 0)
//        {
//            this.indent = " ".Repeat(indent * 4);
//        }

//        public void AppendLine(string code)
//        {
//            if (code.IsNullOrWhiteSpace()) sb.AppendLine();
//            else sb.AppendLine($"{indent}{code}");
//        }

//        public override string ToString()
//        {
//            return sb.ToString();
//        }
//    }
//    #endregion

//    #region 处理消息

//    /// <summary>
//    /// 预注册模型转换,如:
//    /// <list type="number">
//    /// <item>RegisterConvert&lt;Person,PersonDto>();</item>
//    /// <item>RegisterConvert&lt;PersonDto,Person>();</item>
//    /// </list>
//    /// </summary>
//    /// <typeparam name="TSrc">源类型</typeparam>
//    /// <typeparam name="TDest">目标类型</typeparam>
//    /// <remarks>注意：不需要注册集合间转换,程序会自动处理，如下面代码不需要:<br /> 
//    /// <code>RegisterConvert&lt;List&lt;Peson>,List&lt;PersonDto>>();
//    /// </code>
//    /// </remarks>
//    public static void RegisterConvert<TSrc, TDest>() where TSrc : class where TDest : class
//    {
//        RegisterConvert(typeof(TSrc), typeof(TDest));
//    }

//    /// <summary>
//    /// 预注册模型转换,如:
//    /// <list type="number">
//    /// <item>RegisterConvert(typeof(Person),typeof(PersonDto));</item>
//    /// <item>RegisterConvert(typeof(PersonDto),typeof(Person));</item>
//    /// </list>
//    /// </summary>
//    /// <param name="srcType">源类型</param>
//    /// <param name="destType">目标类型</param>
//    /// <remarks>注意：不需要注册集合间转换,程序会自动处理，如下面代码不需要:<br /> 
//    /// <code>RegisterConvert(typeof(List&lt;Person>),typeof(List&lt;Person>));</code>
//    /// </remarks>
//    public static void RegisterConvert(Type srcType, Type destType)
//    {
//        if (srcType == typeof(string) || destType == typeof(string)) throw new ArgumentException($"{nameof(destType)}和{nameof(srcType)} 都不要使用String!");
//        if (srcType.IsValueType || destType.IsValueType) throw new ArgumentException($"{nameof(destType)}和{nameof(srcType)} 都不要使用值类型!");
//        var b1 = srcType.IsConvertCollectionsOrArrary();
//        var b2 = destType.IsConvertCollectionsOrArrary();
//        if (b1 != b2) throw new ArgumentException("转换的源类型和目标类型不能一方为集合,而另一方不是!");

//        initQueue();
//        mapperQueue.TryAdd((srcType, destType));
//    }

//    private static ConcurrentDictionary<(Type srcType, Type destType), Result<Func<object, Dictionary<(object src, Type destType), object>, object>>> cacheFuncs =
//        new ConcurrentDictionary<(Type srcType, Type destType), Result<Func<object, Dictionary<(object src, Type destType), object>, object>>>();

//    private static BlockingCollection<(Type srcType, Type destType)> mapperQueue = new BlockingCollection<(Type srcType, Type destType)>();
//    private static bool isInitQueue = false;

//    private static void initQueue()
//    {
//        if (isInitQueue) return;
//        lock (typeof(RoslynMapper))
//        {
//            if (isInitQueue) return;
//            isInitQueue = true;
//            Task.Factory.StartNew(() =>
//            {
//                while (true)
//                {
//                    var key = mapperQueue.Take();
//                    try
//                    {
//                        if (cacheFuncs.ContainsKey(key)) continue;
//                        var ctx = new RoslynMapper().GenerateMapCode(key.srcType, key.destType);
//                        var result = RoslynHelper.GenerateAssemblyFromCode(ctx.Code);
//                        RoslynMapper.EventRoslynMapperTriggered?.Invoke(ctx, result);
//                        if (!result.Success)
//                        {
//                            //编译失败了也要放进去,防止重复编译
//                            cacheFuncs.TryAdd(key, Result.NotOk(result.Message));
//                            logger.LogError($"Roslyn编译Mapper队列消息(失败): {key.srcType.GetClassFullName()} => {key.destType.GetClassFullName()},错误如下:\r\n{result.Message}");
//                            continue;
//                        }
//                        else
//                        {
//                            logger.LogInformation($"Roslyn编译Mapper队列消息(成功): {key.srcType.GetClassFullName()} => {key.destType.GetClassFullName()},共生成: {ctx.Methods.Count} 个方法, 对外暴露: {ctx.Methods.Count(i => i.IsExpose)} 个方法, 共 {ctx.Methods.Count(i => i.IsToArray == false && i.IsToList == false)} 个类之间的转换, 自动生成了: {ctx.Methods.Count(i => i.IsToList || i.IsToArray)} 个集合/数组方法,其中分裂出了: {ctx.Methods.Count(i => i.IsSplit)} 个方法.");
//                        }
//                        var geneType = result.Data.GetType(ctx.ClassName);
//                        for (var i = 0; i < ctx.Methods.Count; i++)
//                        {
//                            var method = ctx.Methods[i];

//                            //非暴露的略过
//                            if (!method.IsExpose) continue;
//                            key = (method.SrcType, method.DestType);
//                            //已有的略过
//                            if (cacheFuncs.ContainsKey(key)) continue;

//                            var methodInfo = geneType.GetMethod(method.MethodName);

//                            //IL生成
//                            DynamicMethod md = new DynamicMethod("commonmapper", typeof(object), new Type[] { typeof(object), typeof(Dictionary<(object src, Type destType), object>) }, typeof(RoslynMapper).Module);
//                            ILGenerator il = md.GetILGenerator();

//                            il.Emit(OpCodes.Ldarg_0);
//                            il.Emit(OpCodes.Ldarg_1);
//                            il.Emit(OpCodes.Call, methodInfo);
//                            il.Emit(OpCodes.Ret);

//                            var func = (Func<object, Dictionary<(object src, Type destType), object>, object>)md.CreateDelegate(typeof(Func<object, Dictionary<(object src, Type destType), object>, object>));

//                            if (method.IsToArray || method.IsToList)
//                            {
//                                Type destArrayType = method.IsToArray ? method.InnerMap.DestType.MakeArrayType() : typeof(List<>).MakeGenericType(method.InnerMap.DestType);

//                                //IEnumerable<Person> => PersonDto[]/List<PersonDto>
//                                var srcType2 = typeof(IEnumerable<>).MakeGenericType(method.InnerMap.SrcType);
//                                key = (srcType2, destArrayType);
//                                cacheFuncs.TryAdd(key, Result.Ok(func));

//                                //ICollection<Person> => PersonDto[]/List<PersonDto>
//                                srcType2 = typeof(ICollection<>).MakeGenericType(method.InnerMap.SrcType);
//                                key = (srcType2, destArrayType);
//                                cacheFuncs.TryAdd(key, Result.Ok(func));

//                                //IList<Person> => PersonDto[]/List<PersonDto>
//                                srcType2 = typeof(IList<>).MakeGenericType(method.InnerMap.SrcType);
//                                key = (srcType2, destArrayType);
//                                cacheFuncs.TryAdd(key, Result.Ok(func));

//                                //List<Person> => PersonDto[]/List<PersonDto>
//                                srcType2 = typeof(List<>).MakeGenericType(method.InnerMap.SrcType);
//                                key = (srcType2, destArrayType);
//                                cacheFuncs.TryAdd(key, Result.Ok(func));
//                            }
//                            else
//                            {
//                                cacheFuncs.TryAdd(key, Result.Ok(func));
//                            }
//                        }
//                    }
//                    catch (Exception ex)
//                    {
//                        cacheFuncs.TryAdd(key, Result.NotOk($"自编译失败: {ex.Message} {ex.StackTrace}"));
//                        logger.LogError($"自编译失败: {key.srcType.GetClassFullName()} => {key.destType.GetClassFullName()},错误如下:\r\n{ex?.Message}\r\n{ex?.StackTrace}");
//                    }
//                }
//            }, TaskCreationOptions.LongRunning);
//        }
//    }

//    /// <summary>
//    /// 尝试使用Roslyn进行Mapper映射
//    /// </summary>
//    /// <param name="src"></param>
//    /// <param name="destType"></param>
//    /// <returns></returns>
//    internal static Result<object> TryMapper(object src, Type destType)
//    {
//        var srcType = src.GetType();
//        return TryMapper(src, srcType, destType);

//    }

//    /// <summary>
//    /// 尝试使用Roslyn进行Mapper映射
//    /// </summary>
//    /// <param name="src"></param>
//    /// <param name="srcType"></param>
//    /// <param name="destType"></param>
//    /// <returns></returns>
//    internal static Result<object> TryMapper(object src, Type srcType, Type destType)
//    {
//        var key = (srcType, destType);
//        if (cacheFuncs.TryGetValue(key, out var result))
//        {
//            if (result.Success)
//            {
//                var res = result.Data(src, null);
//                return Result.Ok(res);
//            }
//        }
//        initQueue();
//        mapperQueue.TryAdd(key);
//        return Result.NotOk("缓存中没有转换方法!");
//    }
//    #endregion
//}

//internal static class TypeExtensions
//{
//    public static bool IsConvertCollectionsOrArrary(this Type type)
//    {
//        return RoslynMapper.CollectNames.Any(i => type.FullName.StartsWith(i)) || type.IsArray;
//    }
//    public static bool IsConvertCollections(this Type type)
//    {
//        return RoslynMapper.CollectNames.Any(i => type.FullName.StartsWith(i));
//    }
//    public static bool IsConvertArray(this Type type)
//    {
//        return type.IsArray;
//    }
//}
